using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace DragonAwakening.Game
{
    /// <summary>
    /// Scene manager.
    /// </summary>
    public class SceneManager
    {
        private TextureManager textureManager;

        private const float levelFourLayoutDepth = 0.99F;

        private const float levelThreeLayoutDepth = 0.98F;

        private Rectangle levelFourRectangle = new Rectangle(0, 132, 700, 84);

        private Rectangle?[] levelThreeTopRectangles = new Rectangle?[7]
        {
            new Rectangle(0, 125, 76, 8),
            new Rectangle(0, 115, 186, 18),
            new Rectangle(80, 115, 216, 18),
            new Rectangle(260, 115, 181, 18),
            new Rectangle(405, 115, 216, 18),
            new Rectangle(515, 115, 185, 18),
            new Rectangle(625, 125, 75, 8)
        };

        private Rectangle?[] levelThreeBottomRectangles = new Rectangle?[7]
        {
            new Rectangle(0, 216, 76, 16),
            new Rectangle(0, 216, 186, 37),
            new Rectangle(80, 216, 216, 37),
            new Rectangle(260, 216, 181, 37),
            new Rectangle(405, 216, 216, 37),
            new Rectangle(515, 216, 185, 37),
            new Rectangle(625, 216, 75, 16)
        };

        private Rectangle?[] levelThreeBackRectangles = new Rectangle?[7]
        {
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle()
        };

        private Rectangle?[] levelThreeFrontRectangles = new Rectangle?[7]
        {
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle()
        };

        private Rectangle?[] levelThreeLeftRectangles = new Rectangle?[7]
        {
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle()
        };

        private Rectangle?[] levelThreeRightRectangles = new Rectangle?[7]
        {
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle(),
            new Rectangle()
        };

        private char[] sidesMap = new char[6] {'F', 'F', 'S', 'S', 'B', 'T' };

        // Constructs the scene manager.
        public SceneManager(TextureManager textureManager)
        {
            this.textureManager = textureManager;
        }

        // Draws the scene
        public void DrawScene(GraphicsDevice device, SpriteBatch spriteBatch)
        {
            this.DrawLayer(spriteBatch, null, 4);
            this.DrawLayer(spriteBatch, new MapCell[] { new MapCell(0, 0, 1, 1, 1, 1, 1, 1), null, null, null, null, null, null }, 3);
            /*
            // Draw level 3
            var levelThreeLayoutDepth = 0.98F;
            
            // Level 3 top
            bool levelThreeTopIsDrawn = true;
            if (levelThreeTopIsDrawn)
            {
                var levelThreeTopTexture = this.manager.Get(3, 'T', 1);
                if (levelThreeTopTexture != null)
                {
                    var levelThreeTopRectangle = new Rectangle(260, 115, 180, 17);
                    this.spriteBatch.Draw(levelThreeTopTexture, levelThreeTopRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);
                }
            }

            // Level 3 bottom
            bool levelThreeBottomIsDrawn = true;
            if (levelThreeBottomIsDrawn)
            {
                var levelThreeBottomTexture = this.manager.Get(3, 'B', 1);
                if (levelThreeBottomTexture != null)
                {
                    var levelThreeBottomRectangle = new Rectangle(260, 216, 180, 36);
                    this.spriteBatch.Draw(levelThreeBottomTexture, levelThreeBottomRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);
                }
            }

            // Level 3 left
            bool levelThreeLeftIsDrawn = true;
            if (levelThreeLeftIsDrawn)
            {
                var levelThreeLeftTexture = this.manager.Get(3, 'S', 1);
                if (levelThreeLeftTexture != null)
                {
                    var levelThreeLeftRectangle = new Rectangle(260, 115, 36, 137);
                    this.spriteBatch.Draw(levelThreeLeftTexture, levelThreeLeftRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);
                }
            }

            // Level 3 right
            bool levelThreeRightIsDrawn = true;
            if (levelThreeRightIsDrawn)
            {
                var levelThreeRightTexture = this.manager.Get(3, 'S', 1);
                if (levelThreeRightTexture != null)
                {
                    var levelThreeRightRectangle = new Rectangle(405, 115, 36, 137);
                    this.spriteBatch.Draw(levelThreeRightTexture, levelThreeRightRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.FlipHorizontally, levelThreeLayoutDepth);
                }
            }

            // Level 3 front
            bool levelThreeSideIsDrawn = true;
            if (levelThreeSideIsDrawn)
            {
                var levelThreeSideTexture = this.manager.Get(3, 'F', 1);
                if (levelThreeSideTexture != null)
                {
                    var levelThreeSideRectangle = new Rectangle(80, 115, 180, 137);
                    //this.spriteBatch.Draw(levelThreeSideTexture, levelThreeSideRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);

                    var levelThreeSideRectangle2 = new Rectangle(-100, 115, 180, 137);
                    //this.spriteBatch.Draw(levelThreeSideTexture, levelThreeSideRectangle2, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);

                    var levelThreeLeftTexture = this.manager.Get(3, 'S', 1);
                    var levelThreeLeftRectangle = new Rectangle(-100, 115, 174, 137);
                    this.spriteBatch.Draw(levelThreeLeftTexture, levelThreeLeftRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelThreeLayoutDepth);
                }
            }
            */
        }

        // Draws the scene
        public void Draw(SpriteBatch sprite)
        {
        }

        // Draws the layer
        public void DrawLayer(SpriteBatch canvas, MapCell[] cubes, short level)
        {
            switch (level)
            {
                case 4:
                    DrawLevelFour(canvas);
                    break;
                case 3:
                    DrawLevelThree(canvas, cubes[0], -3);
                    break;
                case 2:
                    break;
                case 1:
                    break;
                case 0:
                    break;
            }
        }

        // Draws level 4
        private void DrawLevelFour(SpriteBatch canvas)
        {
            canvas.Draw(this.textureManager.GetColorTexture(Color.Black), levelFourRectangle, null, Color.White, 0.0F, Vector2.Zero, SpriteEffects.None, levelFourLayoutDepth);
        }

        // Draws level 3
        private void DrawLevelThree(SpriteBatch canvas, MapCell cell, short offset)
        {
            if (cell == null)
            {
                return;
            }

            short tOffset = (short)(3 - Math.Abs(offset));
            var levelThreeRectanglesToSideMap = new Func<Rectangle?[]>[6]
            { 
                () => levelThreeBackRectangles, 
                () => levelThreeFrontRectangles, 
                () => levelThreeLeftRectangles, 
                () => levelThreeRightRectangles, 
                () => levelThreeBottomRectangles, 
                () => levelThreeTopRectangles 
            };

            foreach (var side in new Sides[] { Sides.Sky, Sides.Floor })
            {
                Rectangle? rect = levelThreeRectanglesToSideMap[(short)side]()[3 + offset];
                if (rect != null)
                {
                    var cubeSide = this.GetCubeSide(side, side);
                    var sideWall = cell.GetWall(cubeSide);
                    if (sideWall > 0)
                    {
                        var textureInfo = this.GetTexturePosition(cubeSide);
                        var texture = this.textureManager.Get(3, textureInfo.Key, sideWall, tOffset);
                        if (texture != null)
                        {
                            canvas.Draw(texture, rect.Value, null, Color.White, 0.0F, Vector2.Zero, textureInfo.Value ? SpriteEffects.FlipHorizontally : SpriteEffects.None, levelThreeLayoutDepth);
                        }
                    }
                }
            }
        }

        // Corrects the side of the cube respecting the group orientation.
        private Sides GetCubeSide(Sides side, Sides directions)
        {
            return side;
        }

        // Gets texture position
        private KeyValuePair<char, bool> GetTexturePosition(Sides lookSide)
        {
            return new KeyValuePair<char, bool>(sidesMap[(short)lookSide], lookSide == Sides.East);
        }
    }
}
